package io.renren.modules.sys.service.impl;

import io.renren.modules.sys.entity.EntityCache;
import io.renren.modules.sys.service.CacheService;
import org.springframework.stereotype.Service;

import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;

/**
 * Title:       CacheServiceLocalMapImpl
 * Description: 缓存服务实现类   使用本地Map 实现单机缓存策略
 *
 * @author : liugaoyang
 * date         : 2019/3/12 11:29
 */
@Service("cacheService")
public class CacheServiceLocalMapImpl implements CacheService {

    private static Map<String, Object> caches = new ConcurrentHashMap<>();

    /**
     * 增加 key - value 形式的键值对至服务器内存中
     * 默认过期时间
     * @param key
     * @param value
     */
    @Override
    public void set(String key, Object value) {
        set(key, value, DEFAULT_EXPIRE);
    }

    /**
     * 增加 key - value 形式的键值对至服务器内存中
     * 允许自定义缓存过期时间
     * @param key
     * @param value
     * @param expire
     */
    @Override
    public void set(String key, Object value, long expire) {
        expire = expire > 0 ? expire : NOT_EXPIRE;
        caches.put(key, new EntityCache(value, expire, System.currentTimeMillis()));
    }

    /**
     * 根据Key得到缓存对象
     * @param key
     * @return
     */
    @Override
    public String get(String key) {
        if (this.isContains(key)) {
            Object o = caches.get(key);
            if(o instanceof EntityCache){
                EntityCache cache = (EntityCache) o;
                try {
                    String data = (String) cache.getData();
                    return data;
                } catch (Exception e) {
                    return null;
                }
            }
        }
        return null;
    }

    /**
     * 根据key删除缓存对象
     * @param key
     */
    @Override
    public void delete(String key) {
        if (this.isContains(key)) {
            caches.remove(key);
        }
    }

    /**
     * 获取所有缓存
     * @return
     */
    @Override
    public Map<String, Object> getCacheAll() {
        return caches;
    }

    /**
     * 判断是否在缓存中
     * @param key
     * @return
     */
    @Override
    public boolean isContains(String key) {
        return caches.containsKey(key);
    }

    /**
     * 缓存是否超时失效
     * @param key
     * @return
     */
    @Override
    public boolean isTimeOut(String key) {
        if (!caches.containsKey(key)) {
            return true;
        }
        Object o = caches.get(key);
        if(!(o instanceof EntityCache)){
            return true;
        }
        EntityCache cache = (EntityCache) o;
        long timeOut = cache.getTimeOut();
        long lastRefreshTime = cache.getLastRefreshTime();
        // 不是不失效缓存，而且当前时间-最后刷新时间 超过 缓存时间，判断为失效
        if (timeOut != NOT_EXPIRE && System.currentTimeMillis() - lastRefreshTime >= timeOut) {
            return true;
        } else {
            return false;
        }
    }

    /**
     * 清除所有缓存
     */
    @Override
    public void clearAll() {
        caches.clear();
    }

    /**
     * 获取所有key
     * @return
     */
    @Override
    public Set<String> getAllKeys() {
        return caches.keySet();
    }

    /**
     * 缓存监控任务 启动线程清空缓存对象
     */
    @Override
    public void startListen() {
        CacheService cs = this;
        final boolean flag = true;
        new Thread(() -> {
            while (flag) {
                for(String key : cs.getAllKeys()) {
                    if (cs.isTimeOut(key)) {
                        cs.delete(key);
                    }
                }
            }
        }).start();
    }

}
